using IQIGame.Onigao.Framework;
using IQIGame.Onigao.Game;
using NetProtocol.Client;
using System;
using System.Threading.Tasks;
using UnityEngine;

namespace IQIGame.Onigao.GamePlay
{
    public class LogicServerModule : Singleton<LogicServerModule>, CNetLogicServer, INetSessionConnector
    {
        private LogicServerModule() { }
        public static CNetLogicServer NetCore => Instance;

        /// <summary>
        /// 是否是测试服务器模式
        /// </summary>
        public bool IsTestMode = false;
        /// <summary>
        /// 当前逻辑服的session
        /// </summary>
        public NetSession CurrSession { get; private set; }
        /// <summary>
        /// 当前逻辑服时间
        /// </summary>
        public DateTime ServerTime => CurrSession == null ? default : CurrSession.GetServerDateTime();
        /// <summary>
        /// 获取游戏服时间戳(毫秒)
        /// </summary>
        public long ServerTimeMillis => CurrSession == null ? 0 : CurrSession.GetServerTimestampMillis();
        /// <summary>
        /// 获取游戏服时间戳(秒)
        /// </summary>
        public int ServerTimestamp => CurrSession == null ? 0 : CurrSession.GetServerTimestamp();

        async Task<bool> INetSessionConnector.ConnectServer(NetSession session, string token, string gameServerId, string accountServerId)
        {
            LogGame.Log($"LogicServer OnSessionConnected channelName = {session.ChannelName}");
            CurrSession = session;
            var connectTask = NetCore.CS_connect(token, gameServerId, accountServerId);
            session.WaitProtocolConnectResult = true;
            var result = await connectTask;
            session.WaitProtocolConnectResult = false;
            if (result.IsSuccess)
            {
                session.OnProtocolConnectSuccess(result.reconnectToken, result.connectId);
                return true;
            }
            else
            {
                LogGame.LogError($"LogicServer SC_connectResult is fail code = {result.code}");
                session.OnProtocolConnectFail();
                return false;
            }

        }

        async Task<bool> INetSessionConnector.ReconnectServer(NetSession session)
        {
            LogGame.LogWarning($"LogicServer OnSessionReconnected channelName = {session.ChannelName}");
            CurrSession = session;
            var reconnectTask = NetCore.CS_reconnect(session.ReconnectToken, session.LastReadMsgCount, session.ConnectId);
            session.WaitProtocolConnectResult = true;
            var result = await reconnectTask;
            session.WaitProtocolConnectResult = false;
            if (result.IsSuccess)
            {
                session.OnProtocolConnectSuccess(result.reconnectToken, result.connectId, result.lastMsgOrder);
                NetTipController.Instance.UpdateStatus(NetTipStatus.LogicSessionReconnectSuccess);
                return true;

            }
            else if (result.IsFail)
            {
                Debug.LogWarning($"LogicServer SC_reconnectResult is fail code = {result.code}");
                session.OnProtocolConnectFail();
                return false;
            }
            else if (result.IsCanceled)
            {
                //TODO:请求被取消了如何处理??
            }
            return false;
        }

        void INetSessionConnector.SendHeartBeat()
        {
            NetCore.CS_ping();
        }

        void INetSessionConnector.OnSessionClosed(NetSession session, bool active)
        {
            CurrSession = null;
            NetLockModule.Instance.ClearLock();
            if (active)
            {
                NetManager.Instance.DestroySession(NetworkChannelName.Logic);
            }
            else
            {
                NetTipController.Instance.UpdateStatus(NetTipStatus.LogicSessionClosed);
            }
            Debug.LogWarning($"LogicServer OnSessionClosed channelName = {session.ChannelName}");
        }

        public void OnSessionDisconnected(NetSession session)
        {
            NetLockModule.Instance.ClearLock();
            if (session.CanReconnect())
            {
                NetTipController.Instance.UpdateStatus(NetTipStatus.LogicSessionDisconnected);
            }
            else
            {
                session.Close();
            }
        }

        void CNetLogicServer.SC_notifyError(ISession session, int code, string msg)
        {
            Debug.LogError($"LogicServer Error code = {code}, msg = {msg}");
        }

        void CNetLogicServer.SC_notifyServerStatus(ISession session, long time, int rawOffset, bool testMode)
        {
            IsTestMode = testMode;
            NetSession netSession = (NetSession)session;
            netSession.SyncServerTime(time, rawOffset);
        }

        void CNetLogicServer.SC_pang(ISession session, long serverTime)
        {
            NetSession netSession = (NetSession)session;
            netSession.ReceiveHeartBeat();
            netSession.SyncServerTime(serverTime);
        }

        ISession CNetLogicServer.GetSession()
        {
            return CurrSession;
        }

        void CNetLogicServer.SC_notifyOffline(ISession session)
        {
        }

        /// <summary>
        /// 获取与当前服务器时间的时间差
        /// </summary>
        public long GetDiffTime(long timeMillis)
        {
            return timeMillis - ServerTimeMillis;
        }

        /// <summary>
        /// 获取转为服务器时间的DateTime
        /// </summary>
        public DateTime GetDateTime(long timeMillis)
        {
            int serverTimeRawOffset = CurrSession == null ? 0 : CurrSession.ServerTimeRawOffset;
            return DateTimeUtil.GetDateTime(timeMillis, serverTimeRawOffset);
        }

        /// <summary>
        /// 获取转为服务器时间的DateTime
        /// </summary>
        public bool TryParseDateStr(string dateTimeFormat, out DateTime outTime)
        {
            int serverTimeRawOffset = CurrSession == null ? 0 : CurrSession.ServerTimeRawOffset;
            return DateTimeUtil.TryParseDateStr(dateTimeFormat, serverTimeRawOffset, out outTime);
        }
    }
}

